
#pragma once

#include "MathCommon.h"
#include "Vec3.h"


class vec4
{
public:
    union
    {
        struct
        {
            float x, y, z, w;
        };
        struct
        {
            float r, g, b, a;
        };
    };
    
    vec4():										  x(0), y(0), z(0), w(0)				 {}
    vec4(float xv, float yv, float zv, float wv): x(xv), y(yv), z(zv), w(wv)			 {}
    vec4(const vec4& vec):						  x(vec.x), y(vec.y), z(vec.z), w(vec.w) {}
	vec4(const vec3& vec, float wv):			  x(vec.x), y(vec.y), z(vec.z), w(wv)    {}
    ~vec4() {}
    
    float length();
	vec4& normalize();
    
    vec4& operator = (const vec4& vec);
    vec4& operator - ();
    
    friend bool		   operator == (const vec4& left, const vec4& right);
    friend vec4&	   operator += (vec4& left, const vec4& right);
    friend vec4&	   operator -= (vec4& left, const vec4& right);
	friend vec4&	   operator *= (vec4& left, const float right);
    friend const vec4  operator +  (const vec4& left, const vec4& right);
    friend const vec4  operator -  (const vec4& left, const vec4& right);
    friend const vec4  operator *  (const vec4& vec, const float right);
    friend const float operator *  (const vec4& left, const vec4& val);
};



inline float vec4::length()
{
    return sqrt(x * x + y * y + z * z + w * w);
}

inline vec4& vec4::normalize()
{
	float invLen = 1.0f / sqrt(x * x + y * y + z * z + w * w);

	x *= invLen;
	y *= invLen;
	z *= invLen;
	w *= invLen;

	return *this;
}

inline vec4& vec4::operator = (const vec4& vec)
{
    x = vec.x;
    y = vec.y;
	z = vec.z;
    w = vec.w;

    return *this;
}

inline vec4& vec4::operator - ()
{
    x *= -1;
    y *= -1;
	z *= -1;
    w *= -1;

    return *this;
}

inline bool operator == (const vec4& left, const vec4& right)
{
    return (left.x == right.x) && 
		   (left.y == right.y) &&
		   (left.z == right.z) && 
		   (left.w == right.w);
}

inline vec4& operator += (vec4& left, const vec4& right)
{
    left.x += right.x;
    left.y += right.y;
	left.z += right.z;
    left.w += right.w;

    return left;
}

inline vec4& operator -= (vec4& left, const vec4& right)
{
    left.x -= right.x;
    left.y -= right.y;
	left.z -= right.z;
    left.w -= right.w;

    return left;
}

inline vec4& operator *= (vec4& left, const float right)
{
	left.x *= right;
    left.y *= right;
	left.z *= right;
    left.w *= right;

    return left;
}

inline const vec4 operator + (const vec4& left, const vec4& right)
{
    vec4 res(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);

    return res;
}

inline const vec4 operator - (const vec4& left, const vec4& right)
{
    vec4 res(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);

    return res;
}

inline const float operator * (const vec4& left, const vec4& right)
{
    return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
}

inline const vec4 operator * (const vec4& vec, const float val)
{
    vec4 res(vec.x * val, vec.y * val, vec.z * val, vec.w * val);

    return res;
}

typedef vec4 ColorRGBA;